package com.example.demo.domain.category;

import com.example.demo.domain.application.Application;
import com.example.demo.domain.category.repository.CategoryApplicationSortRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;

/**
 * 应用分类的排序服务
 *
 * @author yingjianhua
 */
@Service
public class CategoryApplicationSortService {

    @Autowired
    private CategoryApplicationSortRepository sortRepository;

    /**
     * 设置 category 的约束
     */
    private void moveToConstrains(@NotNull Category category) {
        if (!category.getEnable()) {
            // 如果应用分类没有开启，是不能被应用使用的
            throw new RuntimeException("应用分类" + category + "没有开启");
        }
    }

    /**
     * 将应用移动到指定的应用分类下
     * @param application 应用
     * @param newCategory 应用分类
     */
    public void moveToCategory(Application application, @NotNull Category newCategory) {
        // 先对目标分类进行约束判断
        moveToConstrains(newCategory);
        Optional<CategoryApplicationSort> sortOptional = sortRepository.findByApplication(application);
        if (sortOptional.isPresent()) {
            // 若应用原先已经存在分类，还需要额外从原先的分类中删除，并对原先分类中的应用重新排序，最后才将应用添加到目标分类中
            CategoryApplicationSort originSort = sortOptional.get();
            if (!originSort.getCategory().equals(newCategory)) {
                // 目标分类和原来的分类不同才做操作
                List<CategoryApplicationSort> allByCategory = sortRepository.findAllByCategoryOrderBySort(originSort.getCategory());
                // 移除之后需要对原先的sort重新计算排序字段
                int sort = 0;
                for (CategoryApplicationSort applicationSort : allByCategory) {
                    if (applicationSort.getId().equals(originSort.getId())) {
                        sortRepository.delete(applicationSort);
                        continue;
                    }
                    applicationSort.setSort(sort ++);
                    sortRepository.save(applicationSort);
                }
                sortRepository.save(new CategoryApplicationSort(application, newCategory, sortRepository.countByCategory(newCategory)));
            }
        } else {
            // 如果应用还不存在分类， 只需要将应用添加到目标分类中
            sortRepository.save(new CategoryApplicationSort(application, newCategory, sortRepository.countByCategory(newCategory)));
        }
    }

    /**
     * 重新排序应用的位置
     * @param application 应用
     * @param targetSort 目标排序 从0开始
     */
    public void changeSort(Application application, Integer targetSort) {
        CategoryApplicationSort originSort = sortRepository.findByApplication(application).orElseThrow(() -> new RuntimeException("数据异常"));
        Category category = originSort.getCategory();
        List<CategoryApplicationSort> applicationSorts = sortRepository.findAllByCategoryOrderBySort(category);
        if (targetSort >= applicationSorts.size()) {
            throw new IllegalArgumentException("目标排序位置异常");
        }
        for (CategoryApplicationSort applicationSort : applicationSorts) {
            if (application.getId().equals(applicationSort.getApplication().getId())) {
                // 从列表中移除并插到跟排序相对应的位置
                applicationSorts.remove(applicationSort);
                applicationSorts.add(targetSort, applicationSort);
                break;
            }
        }
        int sort = 0;
        for (CategoryApplicationSort applicationSort : applicationSorts) {
            // 根据列表中元素的顺序, 给排序字段重新赋值
            applicationSort.setSort(sort ++);
            sortRepository.save(applicationSort);
        }
    }
}
